package com.symaster.backups.frame.element.collapse;

import com.symaster.backups.util.TimeUtil;
import com.symaster.common.animation.Curve;
import lombok.Getter;
import lombok.Setter;

import javax.swing.*;
import java.awt.*;
import java.util.HashSet;
import java.util.Set;

/**
 * @author yinmiao
 * @version 2024/2/21
 */
public class CollapseItem extends JButton {

    private final Refresh refresh = new Refresh(this);

    @Getter
    @Setter
    private JComponent top, center;

    boolean run = false;
    float runTime;
    boolean optionType = false; // true:展开, false:收起
    int openHeight;

    static final float exec = 200;
    static final Curve c = Curve.TYPE_FAST_TO_SLOW;
    final Set<RefreshListener> refreshListeners = new HashSet<>();
    final Set<OpenListener> openListeners = new HashSet<>();

    public CollapseItem(JComponent top, JComponent center) {
        this.top = top;
        this.center = center;

        setLayout(new CollapseItemLayout());
        add(top, CollapseItemLayout.TOP);

        if (center != null) {
            add(center, CollapseItemLayout.CENTER);
            center.setVisible(false);
        }

        addActionListener(e -> {
            if (!run && CollapseItem.this.center != null) {
                openListeners.forEach(e1 -> e1.before(!optionType));

                if (!optionType) {
                    openHeight = CollapseItem.this.center.getPreferredSize().height;
                }

                runTime = TimeUtil.floatTime();
                optionType = !optionType;
                run = true;
                CollapseItem.this.center.setVisible(true);
            }
        });
    }

    public void addRefreshListener(RefreshListener l) {
        refreshListeners.add(l);
    }

    public void addOpenListener(OpenListener l) {
        openListeners.add(l);
    }

    @Override
    public void paint(Graphics g) {
        doLayout();

        super.paint(g);

        if (run) {
            SwingUtilities.invokeLater(this.refresh);
        }
    }

    private record Refresh(CollapseItem collapseItem) implements Runnable {

        @Override
        public void run() {
            collapseItem.repaint();
            collapseItem.refreshListeners.forEach(RefreshListener::refresh);
        }
    }

    public interface OpenListener {

        /**
         * 展开之前
         *
         * @param optionType true:展开, false:收起
         */
        void before(boolean optionType);

        /**
         * 展开之后
         *
         * @param optionType true:展开, false:收起
         */
        void after(boolean optionType);
    }

    public interface RefreshListener {
        void refresh();
    }
}
